#define _WIN32_DCOM
#include <stdio.h>
#include <wtypes.h>

#import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only

HRESULT InvokeStaticMember(BSTR typeName, BSTR memberName,
  BindingFlags memberType, SAFEARRAY* parameters, VARIANT* retVal)
{
  HRESULT hresult;
  IUnknown* pUnk = NULL;
  _Object* pObj = NULL;
  _Type* pType = NULL;
  _Type* pTypeOfType = NULL;
  _Type* pDesiredType = NULL;
  VARIANT typeNameParam;
  VARIANT getTypeRetVal;
  VARIANT nullObject;
  SAFEARRAY* psa;
  LONG index;
  BSTR getTypeName = SysAllocString(L"GetType");

  VariantInit(&typeNameParam);
  VariantInit(&getTypeRetVal);
  VariantInit(&nullObject);

  // Instantiate a dummy class just so we can get a System.Type instance
  hresult = CoCreateInstance(CLSID_Object, NULL,
    CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
  if (FAILED(hresult)) goto cleanup;

  // Get the _Object interface so we can call GetType
  hresult = pUnk->QueryInterface(IID__Object, (void**)&pObj);
  if (FAILED(hresult)) goto cleanup;

  // Call _Object.GetType
  hresult = pObj->GetType(&pType);
  if (FAILED(hresult)) goto cleanup;

  // Call the instance Type.GetType method (inherited from Object)
  // in order to get the type for System.Type rather than the type for
  // System.Object
  hresult = pType->GetType(&pTypeOfType);
  if (FAILED(hresult)) goto cleanup;

  // Prepare a 1-element array containing the passed-in type name
  // to pass to the static Type.GetType method
  psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
  typeNameParam.vt = VT_BSTR;
  typeNameParam.bstrVal = typeName;
  index = 0;
  hresult = SafeArrayPutElement(psa, &index, &typeNameParam);
  if (FAILED(hresult)) goto cleanup;

  // Invoke the static Type.GetType method using reflection on the
  // type for System.Type in order to get the desired type
  nullObject.vt = VT_EMPTY;
  hresult = pTypeOfType->InvokeMember_3(getTypeName,
    (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public |
    BindingFlags_Static | BindingFlags_FlattenHierarchy), NULL,
    nullObject, psa, &getTypeRetVal);
  if (FAILED(hresult)) goto cleanup;

  // Get the _Type interface so we can call the static InvokeMember
  // method on the desired type to invoke the desired static member
  hresult = getTypeRetVal.punkVal->QueryInterface(IID__Type,
    (void**)&pDesiredType);
  if (FAILED(hresult)) goto cleanup;

  // Invoke the desired static member
  pDesiredType->InvokeMember_3(memberName, (BindingFlags)(memberType |
    BindingFlags_Public | BindingFlags_Static |
    BindingFlags_FlattenHierarchy), NULL, nullObject, parameters,
    retVal);
  if (FAILED(hresult)) goto cleanup;

cleanup:
  if (pUnk) pUnk->Release();
  if (pObj) pObj->Release();
  if (pType) pType->Release();
  if (pTypeOfType) pTypeOfType->Release();
  if (pDesiredType) pDesiredType->Release();
  if (getTypeName) SysFreeString(getTypeName);
  SafeArrayDestroy(psa);
  VariantClear(&typeNameParam);
  VariantClear(&getTypeRetVal);
  VariantClear(&nullObject);

  return hresult;
};

int main(int argc, char* argv[])
{
  HRESULT hresult;
  VARIANT retVal;
  _AppDomain* pDomain = NULL;
  BSTR typeName1, typeName2, memberName1, memberName2, directory;

  // Initialize COM
  hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
    return -1;
  }

  VariantInit(&retVal);

  // ------------------------------------------
  // Example 1: Calling System.Console.ReadLine
  // ------------------------------------------

  typeName1 = SysAllocString(L"System.Console");
  memberName1 = SysAllocString(L"ReadLine");

  printf("Type in something followed by Enter: ");

  hresult = InvokeStaticMember(typeName1, memberName1,
    BindingFlags_InvokeMethod, NULL, &retVal);
  if (FAILED(hresult))
  {
    printf("ERROR: Invocation failed: 0x%x\n", hresult);
    return -1;
  }

  wprintf(L"You typed: '%s'\n", retVal.bstrVal);

  // --------------------------------------------------
  // Example 2: Calling System.AppDomain.CurrentDomain
  // --------------------------------------------------

  typeName2 = SysAllocString(L"System.AppDomain");
  memberName2 = SysAllocString(L"CurrentDomain");

  hresult = InvokeStaticMember(typeName2, memberName2,
    BindingFlags_GetProperty, NULL, &retVal);
  if (FAILED(hresult))
  {
    printf("ERROR: Invocation failed: 0x%x\n", hresult);
    return -1;
  }

  // Get the _AppDomain interface from the returned IUnknown pointer
  hresult = retVal.punkVal->QueryInterface(IID__AppDomain,
    (void**)&pDomain);
  if (FAILED(hresult))
  {
    printf("ERROR: Could not get _AppDomain interface pointer: 0x%x\n",
      hresult);
    return -1;
  }

  // Call the BaseDirectory property on the _AppDomain instance
  pDomain->get_BaseDirectory(&directory);
  wprintf(L"Base directory of the current domain: '%s'\n", directory);

  CoUninitialize();
  return 0;
};



#define _WIN32_DCOM
#include <stdio.h>
#include <wtypes.h>

// Reference the two necessary type libraries
#import "path\\mscoree.tlb" no_namespace named_guids raw_interfaces_only
#import "path\\mscorlib.tlb" no_namespace named_guids raw_interfaces_only

IUnknown* pUnk = NULL;
IUnknown* pUnk2 = NULL;
ICorRuntimeHost* pHost = NULL;
_AppDomain* pDomain = NULL;
_ObjectHandle* pHandle = NULL;
IDispatch* pDisp = NULL;

BSTR asmName;
BSTR typeName;
VARIANT arrayList;
VARIANT param;

void Cleanup()
{
  pHost->Stop();
  if (pUnk) pUnk->Release();
  if (pUnk2) pUnk2->Release();
  if (pDisp) pDisp->Release();
  if (pHandle) pHandle->Release();
  if (pDomain) pDomain->Release();
  if (pHost) pHost->Release();
  if (asmName) SysFreeString(asmName);
  if (typeName) SysFreeString(typeName);
  VariantClear(&param);
  VariantClear(&arrayList);
  CoUninitialize();
};

int main(int argc, char* argv[])
{
  HRESULT hresult;

  // Initialize COM
  hresult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot initialize COM: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Initialize the CLR
  hresult = CoCreateInstance(CLSID_CorRuntimeHost, NULL,
    CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot create host object: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Get the ICorRuntimeHost interface
  hresult = pUnk->QueryInterface(IID_ICorRuntimeHost, (void**)&pHost);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot get ICorRuntimeHost interface pointer: 0x%x\n",
      hresult);
    Cleanup();
    return -1;
  }

  // Start the host
  hresult = pHost->Start();
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot start host: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Get the default domain
  hresult = pHost->GetDefaultDomain(&pUnk2);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot get default domain: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Get the _AppDomain interface
  hresult = pUnk2->QueryInterface(IID__AppDomain, (void**)&pDomain);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot get _AppDomain interface pointer: 0x%x\n",
      hresult);
    Cleanup();
    return -1;
  }

  // Strings for CreateInstance_3
  asmName = SysAllocString(L"mscorlib");
  typeName = SysAllocString(L"System.Collections.ArrayList");

  // Create a 1D array with one integer element
  SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
  VariantInit(&param);
  param.vt = VT_I4;
  param.lVal = 128;
  LONG index = 0;

  hresult = SafeArrayPutElement(psa, &index, &param);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot set SAFEARRAY element: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Create an instance of ArrayList using a parameterized constructor
  hresult = pDomain->CreateInstance_3(asmName, typeName, VARIANT_TRUE,
    BindingFlags_Default, NULL, psa, NULL, NULL, NULL, &pHandle);
  if (FAILED(hresult))
  {
    printf("ERROR: Cannot create instance: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Unwrap the ArrayList instance inside the ObjectHandle
  VariantInit(&arrayList);
  hresult = pHandle->Unwrap(&arrayList);
  if (FAILED(hresult))
  {
    printf("ERROR: Could not unwrap object handle: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Get the IDispatch interface so we can call the Capacity property
  hresult = arrayList.punkVal->QueryInterface(IID_IDispatch,
    (void**)&pDisp);
  if (FAILED(hresult))
  {
    printf("ERROR: Could not get IDispatch interface pointer: 0x%x\n",
      hresult);
    Cleanup();
    return -1;
  }

  // Get the DISPID for the Capacity property
  OLECHAR* name = L"Capacity";
  DISPID dispid;
  hresult = pDisp->GetIDsOfNames(IID_NULL, &name, 1, GetUserDefaultLCID(),
    &dispid);
  if (FAILED(hresult))
  {
    printf("ERROR: GetIDsOfNames failed: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  // Invoke the Capacity property
  VARIANT result;
  VariantInit(&result);
  DISPPARAMS params = { NULL, NULL, 0, 0 };

  hresult = pDisp->Invoke(dispid, IID_NULL, GetUserDefaultLCID(),
    DISPATCH_PROPERTYGET, &params, &result, NULL, NULL);
  if (FAILED(hresult))
  {
    printf("ERROR: Invoke failed: 0x%x\n", hresult);
    Cleanup();
    return -1;
  }

  printf("ArrayList Capacity: %d\n", result.lVal);

  Cleanup();
  return 0;
};

					  

					

// http://social.msdn.microsoft.com/Forums/vstudio/en-US/ce105a9b-837d-4384-ac03-287b45c1ecc9/marshalling-safearray-of-user-defined-struct					
					  
					  
					  
					  __declspec(dllexport) SAFEARRAY * music_library_get_songs()

	{

		USES_CONVERSION;

		HRESULT hr = S_OK;



		// safe array dim

		SAFEARRAYBOUND safeArrayDim[1];

		safeArrayDim[0].lLbound = 0;

		safeArrayDim[0].cElements = 5;



		// create safe array

		SAFEARRAY * pSafeArray = SafeArrayCreate(VT_VARIANT,1,safeArrayDim);



		// fill safe array with data

		if(pSafeArray != NULL) {

			unsigned int i;

			long index;

			pSafeArray->pvData = malloc(5*sizeof(t_song));

			for(i = safeArrayDim[0].lLbound; i < safeArrayDim[0].cElements + safeArrayDim[0].lLbound; i++) {

				VARIANT vOut;

				VariantInit(&vOut);

				t_song * song = (t_song*)malloc(sizeof(t_song));

				song->album = "album";

				song->artist = "artist";

				song->name = "name";

				/* i don't know how to connect the song structure with the VARIANT 

				*/

				hr = SafeArrayPutElement(pSafeArray, &index, &vOut);

				VariantClear(&vOut);

			}

		}

		return pSafeArray;

	}
managed c# code
// structure marshaling

[StructLayout(LayoutKind.Sequential)]

        public class Song

        {

           [MarshalAs(UnmanagedType.LPTStr)]

           public string name;

           [MarshalAs(UnmanagedType.LPStr)]

           public string album;

           [MarshalAs(UnmanagedType.LPStr)]

           public string artist;        



        }





[DllImport(MyLibrary.dll)]

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_VARIANT)]




USES_CONVERSION;  // enables use of ATL conversion macro A2W
char buffer[20];  // used to store ANSI string
HRESULT hr= S_OK;

// Create SafeArray of VARIANT BSTRs
SAFEARRAY *pSA;
SAFEARRAYBOUND aDim[1];    // a one dimensional array
aDim[0].lLbound= 0;  // Visual Basic arrays start with index 0
aDim[0].cElements= 10;
pSA= SafeArrayCreate(VT_VARIANT,1,aDim);  // create a 1D SafeArray of VARIANTS
if (pSA != NULL) {
    long aLong[1];
    // iterate over array adding VARIANTs of type VT_BSTR
    for (long l= aDim[0].lLbound; l< (aDim[0].cElements + aDim[0].lLbound); l++) { 
        VARIANT vOut;
        VariantInit(&vOut);
        vOut.vt= VT_BSTR;  // set type
        ltoa(l,buffer,10);  // convert long to ANSI string value
        vOut.bstrVal= ::SysAllocString(A2W(buffer)); // system wide "new"
        aLong[0]= l;  // set index value
        if (hr= SafeArrayPutElement(pSA, aLong, &vOut)) { // "correctly" copies VARIANT
            VariantClear(&vOut);  // release BSTR from memory on error
            SafeArrayDestroy(pSA); // does a deep destroy on error
            return hr;
        }
        VariantClear(&vOut);  // does a deep destroy of source VARIANT
    } // end iteration
}
// clean up here only if you do not return SafeArray as an [out, retval]
SafeArrayDestroy(pSA); // again does a deep destroy




// Learning DCOM book on Safary
void CallOcrImage(IOcr *pIOcr, BYTE *pImage, ULONG len)
{
   // Create a one-dimensional SAFEARRAY of BYTEs (VT_UI)
   // The size of this array is len, which represents our image length.
   SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
   // Access the data pointer
   unsigned char *pc = NULL;
   SafeArrayAccessData(psa, reinterpret_cast<void HUGEP**>(&pc));
   // Copy our binary image data into array
   memcpy(pc, pImage, len);
   // Done accessing, so unaccess now.
   SafeArrayUnaccessData(psa);
   // Now we've got the array, we need to store it in
   // a VARIANT (the value holder).
   VARIANT vImage;           // So, let's create a variant
   VariantInit(&vImage); // Initialize the variant
   // Tell the value holder it's holding a SAFEARRAY of bytes
   binaryImageArray.vt = (VT_ARRAY|VT_UI1) ;
   binaryImageArray.parray = psa;   // Let the variant hold the array
   // Yes!  That much set up work before we can invoke a method!
   // Now for the method invocation...
    BSTR pOcrText ;  // Where the OCR text will be stored
    HRESULT hr = pIOcr->OcrImage(vImage, &pOcrText);
   if (SUCCEEDED(hr)) {
      m_strOCRResults = pOcrText ;
      SysFreeString(pOcrText) ;
   }
   SafeArrayDestroyData(psa);  // Destroy the data within the SAFEARRAY
   SafeArrayDestroy(psa);      // Destroy the SAFEARRAY
   // Clear the data
   VariantClear(&binaryImageArray);
}



void CVcpphostclrDlg::OnTestmanagedclassButton()

   HRESULT hRes;
   ICorRuntimeHost *pRuntimeHost;
   IUnknown *pUnkAppDomain;
   _AppDomain *pAppDomain;
   _ObjectHandle *pHandle;
   OLECHAR *methodName=L"GetSalary";
   VARIANT vntResult;
   float fltVal;
   DISPID dispid;
   EXCEPINFO errorInfo;
   UINT intArg;
   DISPPARAMS param;
   BSTR bstrTypeName, bstrAssemblyName;
   SAFEARRAY *paramArray;
   VARIANT paramID, paramName;
   VARIANT paramSalary, paramBonus;
   LONG index;
   hRes=CoInitializeEx(NULL,COINIT_MULTITHREADED);
   if (FAILED(hRes))
       AfxMessageBox("Could not initialize COM");
   hRes=CoCreateInstance(CLSID_CorRuntimeHost,
       NULL,CLSCTX_INPROC_SERVER,
       IID_ICorRuntimeHost,
       (void **)&pRuntimeHost);
   if (FAILED(hRes))
       AfxMessageBox("Could not create host");
   hRes=pRuntimeHost->Start();
   hRes=pRuntimeHost->GetDefaultDomain(
       &pUnkAppDomain);
   if (FAILED(hRes))
       AfxMessageBox("Could not get Appdomain");
   hRes=pUnkAppDomain->QueryInterface(
       IID__AppDomain,(void **)&pAppDomain);
   if (FAILED(hRes))
       AfxMessageBox("Failed to get domain");
   if (pUnkAppDomain!=NULL)
       pUnkAppDomain->Release();
   bstrTypeName=SysAllocString(
       L"AssemblyDemo.Manager");
   bstrAssemblyName=SysAllocString(
       L"multifile3,Version=2.0.0.0,Culture=neutral,
         PublicKeyToken=8a707be49fd7d8f4");
   paramArray=SafeArrayCreateVector(VT_VARIANT,0,4);

   VariantInit(&paramID);
   paramID.vt=VT_I4;
   paramID.lVal=45;
   index=0;
   hRes=SafeArrayPutElement(paramArray,
       &index,&paramID);
   VariantInit(&paramName);
   paramName.vt=VT_BSTR;
   paramName.bstrVal=SysAllocString(L"Alan Gordon");
   index=1;
   hRes=SafeArrayPutElement(paramArray,
       &index,&paramName);
   VariantInit(&paramSalary);
   paramSalary.vt=VT_R4;
   paramSalary.fltVal=1000.0;
   VariantChangeType(&paramSalary,&paramSalary,
       0,VT_DECIMAL);
   index=2;
   hRes=SafeArrayPutElement(paramArray,
       &index,&paramSalary);
   VariantInit(&paramBonus);
   paramBonus.vt=VT_R4;
   paramBonus.fltVal=100.0;
   VariantChangeType(&paramBonus,&paramBonus,
       0,VT_DECIMAL);
   index=3;
   hRes=SafeArrayPutElement(paramArray,
       &index,&paramBonus);
   hRes=pAppDomain->CreateInstance_3(
       bstrAssemblyName,bstrTypeName,VARIANT_TRUE,
       BindingFlags_Default,NULL,paramArray,
       NULL,NULL,NULL,&pHandle);
   if (FAILED(hRes))
       AfxMessageBox("Could not create object");
   VARIANT vntObject;
   IDispatch *pObject;
   VariantInit(&vntObject);
   pHandle->Unwrap(&vntObject);
   vntObject.punkVal->QueryInterface(IID_IDispatch,
       (void **)&pObject);
   if (vntObject.punkVal!=NULL)
       vntObject.punkVal->Release();

   param.cArgs=0;
   param.rgvarg=NULL;
   param.cNamedArgs=0;
   param.rgdispidNamedArgs=NULL;
   VariantInit(&vntResult);
   hRes=pObject->GetIDsOfNames(IID_NULL,
       &methodName,1,GetUserDefaultLCID(),&dispid);
   hRes=pObject->Invoke(dispid,IID_NULL,
       GetUserDefaultLCID(),
       DISPATCH_METHOD,&param,&vntResult,
       &errorInfo,&intArg);
   if (SUCCEEDED(hRes))
   {
       vntResult.decVal;
       VarR4FromDec(&vntResult.decVal,&fltVal);
   }
   else
   {
   // Handle the error, code omitted...
   }
   if (pObject!=NULL)
       pObject->Release();
   if (pAppDomain!=NULL)
       pAppDomain->Release();

   SysFreeString(bstrTypeName);
   SysFreeString(bstrAssemblyName);
   SafeArrayDestroy(paramArray);
}


					  


					  
					  
					  // _bstr_t_Assign.cpp

#include <comdef.h>
#include <stdio.h>

int main()
{
    // creates a _bstr_t wrapper
    _bstr_t bstrWrapper; 

    // creates BSTR and attaches to it
    bstrWrapper = "some text";
    wprintf_s(L"bstrWrapper = %s\n",
              static_cast<wchar_t*>(bstrWrapper));

    // bstrWrapper releases its BSTR
    BSTR bstr = bstrWrapper.Detach();
    wprintf_s(L"bstrWrapper = %s\n", 
              static_cast<wchar_t*>(bstrWrapper));
    // "some text" 
    wprintf_s(L"bstr = %s\n", bstr);

    bstrWrapper.Attach(SysAllocString(OLESTR("SysAllocedString")));
    wprintf_s(L"bstrWrapper = %s\n", 
              static_cast<wchar_t*>(bstrWrapper));

    // assign a BSTR to our _bstr_t
    bstrWrapper.Assign(bstr);
    wprintf_s(L"bstrWrapper = %s\n", 
              static_cast<wchar_t*>(bstrWrapper));

    // done with BSTR, do manual cleanup
    SysFreeString(bstr);

    // resuse bstr
    bstr= SysAllocString(OLESTR("Yet another string"));
    // two wrappers, one BSTR 
    _bstr_t bstrWrapper2 = bstrWrapper;   

    *bstrWrapper.GetAddress() = bstr;

    // bstrWrapper and bstrWrapper2 do still point to BSTR
    bstr = 0;   
    wprintf_s(L"bstrWrapper = %s\n", 
              static_cast<wchar_t*>(bstrWrapper));
    wprintf_s(L"bstrWrapper2 = %s\n", 
              static_cast<wchar_t*>(bstrWrapper2));

    // new value into BSTR
    _snwprintf_s(bstrWrapper.GetBSTR(), 100, bstrWrapper.length(),
                 L"changing BSTR");   
    wprintf_s(L"bstrWrapper = %s\n", 
              static_cast<wchar_t*>(bstrWrapper));
    wprintf_s(L"bstrWrapper2 = %s\n", 
              static_cast<wchar_t*>(bstrWrapper2));
}



HRESULT PASCAL __export CPoly::EnumPoints(IEnumVARIANT FAR* FAR* ppenum)
{
  unsigned int i;
  HRESULT hresult;
  VARIANT var;
  SAFEARRAY FAR* psa;
  CEnumPoint FAR* penum;
  POINTLINK FAR* ppointlink;
  SAFEARRAYBOUND rgsabound[1];
  rgsabound[0].lLbound = 0;
  rgsabound[0].cElements = m_cPoints;

  psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
  if(psa == NULL){
    HRESULT = ResultFromScode(E_OUTOFMEMORY);
    goto LError0;
  }

  // Code omitted here for brevity.

    V_VT(&var) = VT_DISPATCH;
    HRESULT = ppointlink->ppoint->QueryInterface(
    IID_IDispatch, (void FAR* FAR*)&V_DISPATCH(&var));
    if(HRESULT != NOERROR)
      goto LError1;

    ix[0] = i;
    SafeArrayPutElement(psa, ix, &var);

    ppointlink = ppointlink->next;
  }

  HRESULT = CEnumPoint::Create(psa, &penum);
  if(HRESULT != NOERROR)
    goto LError1;
  *ppenum = penum;
  return NOERROR;

LError1:;
  SafeArrayDestroy(psa);

LError0:;
  return hresult;
}

// http://social.msdn.microsoft.com/Forums/vstudio/en-US/cdc68fd4-08d5-4bfd-8dd7-6c095bd619a6/any-easy-way-to-create-a-safearray
void AlternativeSetSafeArrayData(/*[in]*/ SAFEARRAY* psaStrings)
{
  BSTR  bstr = ::SysAllocString(OLESTR("Another BSTR."));
  VARIANT var;
  long  lIndexVector[1];

  lIndexVector[0] = 0;
  
  VariantInit(&var);
  VariantClear(&var);
  V_VT(&var) = VT_BSTR;
  V_BSTR(&var) = bstr;

  SafeArrayPutElement
  (
    psaStrings, 
    (long*)lIndexVector,
    (void*)&var
  );
  
  VariantClear(&var);
}



